#include "MatUtil.h"
#include < algorithm>
#undef min
#undef max
void ColorToVec4b(DWORD color, cv::Vec4b &vec)
{
    vec[0] = color & 0xff;
    vec[1] = (color >> 8) & 0xff;
    vec[2] = (color >> 16) & 0xff;
    vec[3] = (color >> 24) & 0xff;
}
void Vec4bToColor(const cv::Vec4b &vec, DWORD &color)
{
    color = vec[0] | (vec[1] << 8) | (vec[2] << 16) | (vec[3] << 24);
}
cv::Mat HBITMAPToMat(HBITMAP hBitmap)
{
    if (!hBitmap)
        return cv::Mat(); // 空句柄检查

    // 获取位图基础信息（宽度、高度、位深等）
    BITMAP bmp = {0};
    if (!GetObject(hBitmap, sizeof(BITMAP), &bmp))
        return cv::Mat();

    const int width = bmp.bmWidth;
    const int height = bmp.bmHeight;
    const int bitsPerPixel = bmp.bmBitsPixel;
    const int channels = bitsPerPixel / 8;

    // 仅支持 24位（3通道）和 32位（4通道）图像
    if (channels != 3 && channels != 4)
        return cv::Mat();

    // 创建兼容DC用于获取位图数据
    HDC hdc = GetDC(nullptr);
    if (!hdc)
        return cv::Mat();

    HBITMAP hOldBitmap = (HBITMAP)SelectObject(hdc, hBitmap);

    // 初始化位图信息结构体
    BITMAPINFO bmi = {0};
    bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmi.bmiHeader.biWidth = width;
    bmi.bmiHeader.biHeight = height; // 正数表示位图从下到上存储
    bmi.bmiHeader.biPlanes = 1;
    bmi.bmiHeader.biBitCount = bitsPerPixel;
    bmi.bmiHeader.biCompression = BI_RGB;

    // 分配缓冲区存储像素数据（考虑行对齐填充）
    const int bufferSize = bmp.bmWidthBytes * height;
    std::vector<uchar> pixelBuffer(bufferSize);

    // 提取位图像素数据到缓冲区
    if (!GetDIBits(hdc, hBitmap, 0, height, pixelBuffer.data(), &bmi, DIB_RGB_COLORS))
    {
        SelectObject(hdc, hOldBitmap);
        ReleaseDC(nullptr, hdc);
        return cv::Mat();
    }

    // 创建OpenCV矩阵并填充数据（调整行顺序：Windows位图从下到上，Mat从上到下）
    cv::Mat mat(height, width, CV_MAKETYPE(CV_8U, channels));
    for (int y = 0; y < height; ++y)
    {
        // 位图第y行对应Mat的第(height-1-y)行（上下翻转）
        uchar *src = pixelBuffer.data() + y * bmp.bmWidthBytes; // 源数据（含填充）
        uchar *dst = mat.ptr(height - 1 - y);                   // 目标行（无填充）
        memcpy(dst, src, width * channels);                     // 仅复制有效像素数据（跳过填充）
    }

    // 清理资源
    SelectObject(hdc, hOldBitmap);
    ReleaseDC(nullptr, hdc);

    return mat;
}
HBITMAP MatToHBITMAP(const cv::Mat &mat)
{
    if (mat.empty())
        return NULL;

    // 确保是 8 位图像
    cv::Mat mat8u;
    if (mat.depth() != CV_8U)
    {
        double minVal, maxVal;
        cv::minMaxLoc(mat, &minVal, &maxVal);
        mat.convertTo(mat8u, CV_8U, 255.0 / (maxVal - minVal), -minVal * 255.0 / (maxVal - minVal));
    }
    else
    {
        mat8u = mat;
    }

    // 处理通道数
    cv::Mat bgrMat;
    if (mat8u.channels() == 1)
    {
        cv::cvtColor(mat8u, bgrMat, cv::COLOR_GRAY2BGR);
    }
    else if (mat8u.channels() == 4)
    {
        cv::cvtColor(mat8u, bgrMat, cv::COLOR_BGRA2BGR);
    }
    else
    {
        bgrMat = mat8u;
    }

    const int width = bgrMat.cols;
    const int height = bgrMat.rows;

    // 创建 BITMAPINFO
    BITMAPINFO bmi = {0};
    bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmi.bmiHeader.biWidth = width;
    bmi.bmiHeader.biHeight = -height; // 负号表示从上到下的位图
    bmi.bmiHeader.biPlanes = 1;
    bmi.bmiHeader.biBitCount = 24; // BGR格式
    bmi.bmiHeader.biCompression = BI_RGB;

    // 创建 DIB 位图
    HDC hdc = GetDC(NULL);
    void *pBits = NULL;
    HBITMAP hBitmap = CreateDIBSection(
        hdc, &bmi, DIB_RGB_COLORS, &pBits, NULL, 0);
    ReleaseDC(NULL, hdc);

    if (hBitmap && pBits)
    {
        // 复制图像数据
        const int stride = width * 3;
        for (int y = 0; y < height; y++)
        {
            memcpy(
                (BYTE *)pBits + y * ((stride + 3) & -4), // 4字节对齐
                bgrMat.ptr(y),
                stride);
        }
    }

    return hBitmap;
}

bool SaveBitmapToFile(HBITMAP hBitmap, const wchar_t *lpFilePath)
{
    if (!hBitmap || !lpFilePath)
        return false;

    // 获取位图信息
    BITMAP bm;
    if (!GetObject(hBitmap, sizeof(BITMAP), &bm))
        return false;

    // 创建位图信息头
    BITMAPINFOHEADER bi = {
        sizeof(BITMAPINFOHEADER), // biSize
        bm.bmWidth,               // biWidth
        -bm.bmHeight,             // biHeight (负数表示从上到下扫描)
        1,                        // biPlanes
        bm.bmBitsPixel,           // biBitCount
        BI_RGB,                   // biCompression
        0,                        // biSizeImage
        0,                        // biXPelsPerMeter
        0,                        // biYPelsPerMeter
        0,                        // biClrUsed
        0                         // biClrImportant
    };

    // 计算调色板大小
    WORD colorBits = bm.bmBitsPixel;
    if (colorBits == 1)
        colorBits = 1;
    else if (colorBits <= 4)
        colorBits = 4;
    else if (colorBits <= 8)
        colorBits = 8;
    else
        colorBits = 24;

    WORD numColors = (colorBits <= 8) ? (1 << colorBits) : 0;

    // 创建位图信息结构
    DWORD sizeInfo = sizeof(BITMAPINFOHEADER) + (numColors * sizeof(RGBQUAD));
    BITMAPINFO *pbi = (BITMAPINFO *)new BYTE[sizeInfo];
    if (!pbi)
        return false;

    // 复制位图信息头
    memcpy(&pbi->bmiHeader, &bi, sizeof(BITMAPINFOHEADER));

    // 创建文件
    HANDLE hFile = CreateFile(lpFilePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile == INVALID_HANDLE_VALUE)
    {
        delete[] pbi;
        return false;
    }

    // 创建BITMAPFILEHEADER
    BITMAPFILEHEADER bmfh;
    bmfh.bfType = 0x4D42; // 'BM' 标识
    bmfh.bfSize = 0;      // 将在后面计算
    bmfh.bfReserved1 = 0;
    bmfh.bfReserved2 = 0;
    bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeInfo;

    // 获取DC以访问位图像素数据
    HDC hdcScreen = GetDC(NULL);
    if (!hdcScreen)
    {
        CloseHandle(hFile);
        delete[] pbi;
        return false;
    }

    // 分配缓冲区存储像素数据
    DWORD dwBmpSize = ((bm.bmWidth * colorBits + 31) / 32) * 4 * bm.bmHeight;
    BYTE *lpbitmap = new BYTE[dwBmpSize];
    if (!lpbitmap)
    {
        ReleaseDC(NULL, hdcScreen);
        CloseHandle(hFile);
        delete[] pbi;
        return false;
    }

    // 获取位图像素数据
    if (!GetDIBits(hdcScreen, hBitmap, 0, (UINT)bm.bmHeight, lpbitmap, pbi, DIB_RGB_COLORS))
    {
        delete[] lpbitmap;
        ReleaseDC(NULL, hdcScreen);
        CloseHandle(hFile);
        delete[] pbi;
        return false;
    }

    // 写入BITMAPFILEHEADER到文件
    DWORD dwWritten = 0;
    if (!WriteFile(hFile, (LPSTR)&bmfh, sizeof(BITMAPFILEHEADER), &dwWritten, NULL))
    {
        delete[] lpbitmap;
        ReleaseDC(NULL, hdcScreen);
        CloseHandle(hFile);
        delete[] pbi;
        return false;
    }

    // 写入BITMAPINFO到文件
    if (!WriteFile(hFile, (LPSTR)pbi, sizeInfo, &dwWritten, NULL))
    {
        delete[] lpbitmap;
        ReleaseDC(NULL, hdcScreen);
        CloseHandle(hFile);
        delete[] pbi;
        return false;
    }

    // 写入像素数据到文件
    if (!WriteFile(hFile, (LPSTR)lpbitmap, dwBmpSize, &dwWritten, NULL))
    {
        delete[] lpbitmap;
        ReleaseDC(NULL, hdcScreen);
        CloseHandle(hFile);
        delete[] pbi;
        return false;
    }

    // 更新文件大小
    bmfh.bfSize = bmfh.bfOffBits + dwBmpSize;
    SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
    WriteFile(hFile, (LPSTR)&bmfh, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);

    // 清理资源
    delete[] lpbitmap;
    ReleaseDC(NULL, hdcScreen);
    CloseHandle(hFile);
    delete[] pbi;

    return true;
}

HBITMAP CopyBitmapRegion(HBITMAP hSourceBitmap, const RECT &realRect)
{
    BITMAP bmSrc;
    GetObject(hSourceBitmap, sizeof(BITMAP), &bmSrc);

    HDC hdcScreen = GetDC(NULL);
    HDC hdcSrc = CreateCompatibleDC(hdcScreen);
    HDC hdcDest = CreateCompatibleDC(hdcScreen);

    HBITMAP hOldSrcBmp = (HBITMAP)SelectObject(hdcSrc, hSourceBitmap);

    int width = realRect.right - realRect.left;
    int height = realRect.bottom - realRect.top;

    // 创建32位带Alpha通道的位图
    BITMAPINFO bmi = {0};
    bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmi.bmiHeader.biWidth = width;
    bmi.bmiHeader.biHeight = height;
    bmi.bmiHeader.biPlanes = 1;
    bmi.bmiHeader.biBitCount = 32;
    bmi.bmiHeader.biCompression = BI_RGB;

    void *pBits;
    HBITMAP hDestBitmap = CreateDIBSection(hdcScreen, &bmi, DIB_RGB_COLORS, &pBits, NULL, 0);

    if (hDestBitmap)
    {
        HBITMAP hOldDestBmp = (HBITMAP)SelectObject(hdcDest, hDestBitmap);

        // 使用AlphaBlend保持透明通道
        BLENDFUNCTION blend = {0};
        blend.BlendOp = AC_SRC_OVER;
        blend.SourceConstantAlpha = 255;
        blend.AlphaFormat = AC_SRC_ALPHA;

        AlphaBlend(hdcDest, 0, 0, width, height,
                   hdcSrc, realRect.left, realRect.top, width, height,
                   blend);

        SelectObject(hdcDest, hOldDestBmp);
    }

    SelectObject(hdcSrc, hOldSrcBmp);
    DeleteDC(hdcSrc);
    DeleteDC(hdcDest);
    ReleaseDC(NULL, hdcScreen);

    return hDestBitmap;
}

cv::Mat MakeColorTransparent(const cv::Mat &inputImage, const cv::Vec3b &targetColor, int tolerance)
{ // 确保输入图像有效
    if (inputImage.empty())
    {
        throw std::invalid_argument("Input image is empty");
    }
    if (tolerance < 0)
    {
        tolerance = 0;
    }
    if (tolerance > 255 * 3)
    {
        tolerance = 255 * 3;
    }

    // 转换到BGRA格式（如果输入是3通道，则添加alpha通道）
    cv::Mat resultImage;
    if (inputImage.channels() == 3)
    {
        cv::cvtColor(inputImage, resultImage, cv::COLOR_BGR2BGRA);
    }
    else if (inputImage.channels() == 4)
    {
        resultImage = inputImage.clone();
    }
    else
    {
        throw std::invalid_argument("Input must be 3-channel (BGR) or 4-channel (BGRA) image");
    }

    // 提取目标颜色分量
    uchar targetB = targetColor[0];
    uchar targetG = targetColor[1];
    uchar targetR = targetColor[2];

    // 遍历所有像素
    for (int y = 0; y < resultImage.rows; ++y)
    {
        for (int x = 0; x < resultImage.cols; ++x)
        {
            // 获取当前像素的BGR值
            cv::Vec4b &pixel = resultImage.at<cv::Vec4b>(y, x);
            uchar blue = pixel[0];
            uchar green = pixel[1];
            uchar red = pixel[2];

            // 计算与目标颜色的距离（曼哈顿距离）
            int distance = std::abs(blue - targetB) +
                           std::abs(green - targetG) +
                           std::abs(red - targetR);

            if (distance <= tolerance)
            {
                pixel[3] = 255; // 设置alpha通道
            }
            // 如果在容差范围内，设置alpha为0（完全透明）
            else
            {
                pixel[3] = 0; // 设置alpha通道

                pixel[0] = 0;
                pixel[1] = 0;
                pixel[2] = 0;
            }
        }
    }

    return resultImage;
}
